package org.example.brave.rpc;

import brave.Span;
import brave.propagation.Propagation;

/**
 * Marks an interface for use in {@link RpcClientHandler#handleSend(RpcClientRequest)}. This gives a
 * standard type to consider when parsing an outgoing context.
 *
 * @see RpcClientResponse
 * @since 5.8
 */
public abstract class RpcClientRequest extends RpcRequest {
    static final Propagation.RemoteSetter<RpcClientRequest> SETTER = new Propagation.RemoteSetter<RpcClientRequest>() {
        @Override public Span.Kind spanKind() {
            return Span.Kind.CLIENT;
        }

        @Override public void put(RpcClientRequest request, String key, String value) {
            request.propagationField(key, value);
        }

        @Override public String toString() {
            return "RpcClientRequest::propagationField";
        }
    };

    @Override public final Span.Kind spanKind() {
        return Span.Kind.CLIENT;
    }

    /**
     * Sets a propagation field with the indicated name. {@code null} values are unsupported.
     *
     * <h3>Notes</h3>
     * <p>This is only used when {@link Injector#inject(TraceContext, Object) injecting} a trace
     * context as internally implemented by {@link RpcClientHandler}. Calls during sampling or parsing
     * are invalid and may be ignored by instrumentation.
     *
     * <p>Header based requests will use headers, but this could set RPC
     * envelopes or even binary data.
     *
     * @param keyName key used for {@link Setter#put}
     * @param value value used for {@link Setter#put}
     * @see #SETTER
     * @see Propagation#keys()
     * @see BaggagePropagation#allKeyNames(Propagation)
     * @since 5.12
     */
    protected void propagationField(String keyName, String value) {
    }
}
